package com.zg.message.channel;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONObject;
import com.zg.common.core.dao.message.entity.MsgInfo;

import com.zg.common.core.util.RedisUtil;
import com.zg.common.core.util.TokenUtil;
import com.zg.message.channel.support.MhResult;
import com.zg.message.channel.support.MhToken;
import com.zg.message.channel.support.UndoTaskMsgDto;
import com.zg.message.config.MhConfig;
import com.zg.message.config.MhSmsConfig;
import com.zg.message.service.MsgInfoService;
import com.zg.message.sys.RedisKey;
import com.zg.message.sys.SendStateEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.security.SecureRandom;
import java.util.Date;

/**
 * <p>Description: </p>
 *
 * @author zhanfeng.liang
 * @since 2025/7/9 14:43
 */
@Service
@Slf4j
public class MhChannel implements IChannel {

    @Autowired
    private MsgInfoService msgInfoService;

    @Autowired
    private MhConfig mhConfig;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    public RestTemplate restTemplateNoBalance;
    @Autowired
    private TokenUtil tokenUtil;

    @Override
    public boolean send(MsgInfo msgInfo) {
        String state = SendStateEnum.SUCCESS.getValue();
        try {
            log.info("send mh");
            UndoTaskMsgDto dto = new UndoTaskMsgDto();
            dto.setUsername(msgInfo.getReceiverAdd());
            dto.setDataId(msgInfo.getId().toString());
            dto.setContent(msgInfo.getContent());
            dto.setCreateTime(DateUtil.formatDateTime(msgInfo.getCreateTime()));
            pushUndoTaskMsg(dto);
            return true;
        } catch (Exception e) {
            log.error("调用门户待办接口：{}", e.getMessage());
            state = SendStateEnum.FAIL.getValue();
            return false;
        } finally {
            msgInfo.setSendTime(new Date());
            msgInfo.setSendState(state);
            msgInfoService.edit(msgInfo);
        }
    }

    private String  genTokenUrl(){
        String appSecret = mhConfig.getAppSecret();
        String timestamp=System.currentTimeMillis()+"";
        String random  = generateRandomString(8);
        String sign = SecureUtil.md5(appSecret+timestamp+random);
        return new StringBuilder(mhConfig.getUrl()).append("/un/accessToken/generate")
                .append("?appKey=").append(mhConfig.getAppKey())
                .append("&appSecret=").append(mhConfig.getAppSecret())
                .append("&timestamp=").append(timestamp)
                .append("&random=").append(random)
                .append("&sign=").append(sign)
                .toString();

    }

    private String getMhToken(){
        String token =redisUtil.get(RedisKey.MH_TOKEN);
        if(StrUtil.isEmpty(token)){
            return token;
        }else {
            MhToken mhToken = getAccessTokenFromRemote();
            redisUtil.set(RedisKey.MH_TOKEN,mhToken,getInitExpires(mhToken.getExpiry()));
            return mhToken.getAccessToken();
        }
    }

    /**
     * 提前1分钟过期，提前获取最新token，防止拿到过期token
     * @return
     */
    int getInitExpires(Integer expires){
        return expires-60;
    }


    MhToken getAccessTokenFromRemote(){
        String url=genTokenUrl();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        log.info("[门户][重新获取token]url="+url);
        ResponseEntity<String> response = restTemplateNoBalance.exchange(url, HttpMethod.POST, null, String.class);
        MhResult gateWayResult= JSONObject.parseObject(response.getBody(), MhResult.class);
        if(!gateWayResult.isSuccess()){
            log.error("[门户][获取AccessToken失败][结果]"+gateWayResult);
            throw new RuntimeException("[门户][获取AccessToken失败]"+gateWayResult.getMessage());
        }
        MhToken mhToken= JSONObject.parseObject(gateWayResult.getData(), MhToken.class);
        return mhToken;
    }

    public static String generateRandomString(int length) {
        String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder sb = new StringBuilder(length);
        SecureRandom random = new SecureRandom();
        for (int i = 0; i < length; i++) {
            sb.append(characters.charAt(random.nextInt(characters.length())));
        }
        return sb.toString();
    }

    public HttpHeaders getRequestHeadersJsonType(){
        String accessToken=getMhToken();
        if(accessToken==null){
            throw new RuntimeException("[门户][token获取失败]");
        }
        log.info("[门户][accessToken]"+accessToken);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("accessToken",accessToken);
        return headers;
    }

    public MhResult pushUndoTaskMsg(UndoTaskMsgDto dto) {
        log.info("[门户][pushUndoTaskMsg]"+dto);
        String url= new StringBuilder(mhConfig.getUrl()).append("/un/task/push").toString();
        HttpHeaders headers = getRequestHeadersJsonType();
        String paramsJson=JSONObject.toJSONString(dto);
        HttpEntity<Object> req = new HttpEntity<>(paramsJson, headers);
        ResponseEntity<String> response = restTemplateNoBalance.exchange(url, HttpMethod.POST, req, String.class);
        MhResult gateWayResult= JSONObject.parseObject(response.getBody(), MhResult.class);
        log.error("[门户][pushUndoTaskMsg][result]:"+gateWayResult);
        if(!gateWayResult.isSuccess()){
            log.error("[门户][推送待办消息失败][结果]"+gateWayResult);
            throw new RuntimeException("[门户][推送待办消息失败][结果]"+gateWayResult);
        }
        return gateWayResult;
    }
}
